/**
 * @filename:HabitController 2021年9月13日
 * @project WishStar  V1.0
 * Copyright(c) 2020 huang Co. Ltd.
 * All right reserved.
 */
package com.huang.wishstar.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.huang.wishstar.entity.Habit;
import com.huang.wishstar.entity.RequestData.CreateHabit;
import com.huang.wishstar.entity.RequestData.UpdateHabit;
import com.huang.wishstar.entity.Users;
import com.huang.wishstar.entity.Wish;
import com.huang.wishstar.entity.vo.GetHabitVO;
import com.huang.wishstar.entity.vo.GetHabitWishesVO;
import com.huang.wishstar.entity.vo.GetSavedHabitWishesVO;
import com.huang.wishstar.entity.vo.GetWishVO;
import com.huang.wishstar.service.HabitService;
import com.huang.wishstar.service.UsersService;
import com.huang.wishstar.service.WishService;
import com.huang.wishstar.utils.ApiResponse;
import com.huang.wishstar.utils.Converter;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import io.swagger.annotations.Api;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>自动生成工具：mybatis-dsc-generator</p>
 *
 * <p>说明： 习惯表API接口层</P>
 * @version: V1.0
 * @author: huang
 * @time    2021年9月13日
 *
 */
@Api(tags = "习惯管理",description = "HabitController" )
@RestController
@RequestMapping("/habit")
public class HabitController{
//	extends AbstractController<HabitService,Habit>补充这句可以用自动生成的swagger

    @Autowired
    HabitService habitService;
    @Autowired
    private UsersService usersService;
    @Autowired
    WishService wishService;

    @ApiOperation(value = "首页/创建一个新的习惯记录", notes = "frequency字段表示周一到周日哪几天需要打卡，规定的是7位来判断，如1111100表示周六周日不用打卡；icon为int型表示图标的位置")
    @PostMapping("/create")
    public ApiResponse<String> create(@ApiParam(value="习惯信息",required = true) @RequestBody(required=true) CreateHabit requestData) throws JsonProcessingException {

        if(requestData.getFrequency().length()!=7){
            return ApiResponse.<String>builder().code(400).message("frequency字段长度必须为7").data(null).build();
        }
        Habit habitEntity = new Habit();
        habitEntity.setUserId(requestData.getUserId());
        habitEntity.setHabitTitle(requestData.getHabitTitle());
        habitEntity.setFrequency(requestData.getFrequency());
        habitEntity.setHabitIcon(requestData.getHabitIcon());
        habitEntity.setState(1);
        habitEntity.setDayNum(0);
        habitEntity.setGmtCreate(LocalDate.now());
        Boolean flag = habitService.save(habitEntity);
        if(flag==true){
            return ApiResponse.<String>builder().code(200).message("新建成功").data(null).build();}
        else{
            return ApiResponse.<String>builder().code(400).message("新建失败").data(null).build();
        }
    }

    @ApiOperation(value = "首页/根据habitId删除一个习惯", notes = "")
    //注意是@PathVariable 不是@PathParam ；这个是路径传值
    @DeleteMapping("/delete/{habitId}")
    public ApiResponse<String> DeleteHabitById(@ApiParam(value="习惯id",required = true) @PathVariable("habitId") Integer habitId){
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("habit_id",habitId);
        Boolean b = habitService.remove(wrapper);
        if (b == true){
            return ApiResponse.<String>builder().code(200).message("删除成功").data(b.toString()).build();
        }
        else {
            return ApiResponse.<String>builder().code(400).message("删除失败").data(b.toString()).build();
        }
    }

    @ApiOperation(value = "首页/习惯打卡或归档", notes = "state默认为1即表示习惯坚持中，归档会将state改为2表示不再坚持但又想记录的状态。这个接口默认输入的id都是正确的")
    @PutMapping("/update")
    public ApiResponse<String> update(@ApiParam(value="习惯id必传，习惯状态：打卡传1、归档传2；details字段打卡和归档时可简单描述心情，可用可不用，后端实现了前端不做这功能不传这个字段就行",required = true) @RequestBody(required=true) UpdateHabit requestData) throws JsonProcessingException {

        Habit habitEntity = new Habit();
        if(requestData.getHabitDetails()!=null){
            habitEntity.setHabitDetails(requestData.getHabitDetails());
        }
        //传来的参数state为1，表示需要给该习惯打卡
        if(requestData.getState() ==1){
            //先判断该id对应的习惯是不是已经被删或归档了，因为只有坚持中才能打卡
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("habit_id",requestData.getHabitId());
            wrapper.eq("state",1);//只能对state为1即还在坚持中的习惯打卡
            int isHabitExist = habitService.count(wrapper);
            if(isHabitExist == 0){return ApiResponse.<String>builder().code(400).message("该计划已经被删除或归档，无法打卡").data(null).build();}
            //该习惯还是坚持中的，修改日期变化，天数加一
            habitEntity.setDayNum(habitService.getOne(wrapper).getDayNum()+1);
            habitEntity.setGmtModified(LocalDate.now());
            Boolean flag = habitService.update(habitEntity,wrapper);
            if(flag==true){
                return ApiResponse.<String>builder().code(200).message("打卡成功，坚持天数加一").data(null).build();}
            else{
                return ApiResponse.<String>builder().code(400).message("打卡失败").data(null).build();
            }
        }
        //传入state为2,表示用户想对习惯归档，该操作不增加打卡天数，而会将state变成2，且更新gmt_modified字段表示归档日期
        else{
            habitEntity.setState(requestData.getState());
            QueryWrapper wrapper = new QueryWrapper();
            wrapper.eq("habit_id",requestData.getHabitId());
            wrapper.ne("state",2);//要只能注意修改
            habitEntity.setGmtModified(LocalDate.now());
            Boolean flag = habitService.update(habitEntity,wrapper);
            if(flag==true){
                return ApiResponse.<String>builder().code(200).message("归档成功").data(null).build();}
            else{
                return ApiResponse.<String>builder().code(400).message("归档失败").data(null).build();
            }
        }



    }

    // 合并获取个人习惯和愿望的两个接口，返回首页显示
    @ApiOperation(value = "首页/查找某用户的当天的习惯和未完成的愿望", notes = "这个接口用于首页展示用户的习惯和愿望。实质上是获取用户今天还在坚持的习惯和未完成的愿望两个API接口的合并。返回json中data含habitVOList和wishVOList两个对象列表，前端分别保存再做渲染。" +
            "习惯列表habitVOList中isDoneToday字段为1时表示今天已经打卡，为0表示今天还没打卡；dayNum表示累计打卡天数，该接口返回的state必定都为1表示还在坚持打卡中。" +
            "愿望列表wishVOList中conutdownDays字段距离愿望预期达成日期的倒计时天数。只有两个列表同时为空时data的code才为400，只要有一个不为空code都为200")
    @GetMapping("/getMyhabitAndWish/{userId}")
    @ResponseBody
    public ApiResponse<GetHabitWishesVO> getMyhabitAndWish(@ApiParam(value="用户id",required = true) @PathVariable(value="userId",required=true) Integer userId) {
        //先判断用户是否存在
        QueryWrapper<Users> wrapperUser = new QueryWrapper<>();
        wrapperUser.eq("user_id",userId).last("limit 1");
        int isUserExist = usersService.count(wrapperUser);
        if(isUserExist == 0){
            return ApiResponse.<GetHabitWishesVO>builder().code(400).message("用户id有误").data(null).build();
        }
        //依照用户id和状态（坚持中or归档）来查找出所有的合适记录，之后还要根据frequency进一步筛选
        QueryWrapper<Habit> wrapperHabit = new QueryWrapper<>();
        wrapperHabit.eq("user_id",userId);//要和数据库的一样，带下划线的不能转大写
        wrapperHabit.eq("state",1);
        List<Habit> habitEntities = habitService.list(wrapperHabit);
        List<GetHabitVO> habitVOList = new ArrayList<>();
        //由于需要对frequency进行处理，所以需要先读取字符串中该天对应的标志位是否为1
        for(int i=0;i<habitEntities.size();i++){
            String frequency = habitEntities.get(i).getFrequency();
            //读出来该天的标志位如果为1，即把该记录先转化为vo再添加到列表
            //使用LocalDate则无需调用工具类方法，调用的getDayOfWeek()返回的星期日是7、星期一是1。之后从frequency中取出该天的标志位
            int todayOfWeek= Converter.getAsInteger(LocalDate.now().getDayOfWeek().getValue());
            char todayFlagInFrequency = frequency.charAt(todayOfWeek-1);//获取字符串的第today个字符，注意charAT是从0开始，所以周几需减一，即取出今天是0或1
            int todayFlag = (int)todayFlagInFrequency - (int)('0');
            //今天的标志位为1，意味着要打卡
            if(todayFlag == 1){
                GetHabitVO habitVO = new GetHabitVO();
                habitVO.setHabitId(habitEntities.get(i).getHabitId());
                habitVO.setHabitTitle(habitEntities.get(i).getHabitTitle());
                habitVO.setDayNum(habitEntities.get(i).getDayNum());
                habitVO.setHabitIcon(habitEntities.get(i).getHabitIcon());
                habitVO.setState(habitEntities.get(i).getState());
                habitVO.setHabitDetails(habitEntities.get(i).getHabitDetails());
                habitVO.setFrequency(habitEntities.get(i).getFrequency());
                //判断今日是否打卡，通过gmt_modified字段来确定，如果该字段日期和今天相等，则表示今天已经打过卡
                LocalDate lastDoneTime = habitEntities.get(i).getGmtModified();
                System.out.println("最后打卡时间："+lastDoneTime);
                if(lastDoneTime !=null && lastDoneTime.equals(LocalDate.now()) ){
                    //如果修改日期和今天的日期一致，说明今天已经做过打卡操作了，将isDoneToday字段设置为1
                    habitVO.setIsDoneToday(Converter.getAsInteger(1));
                }
                else{
                    //其他情况比如gmtModified为空是因为习惯刚建立该字段默认为空，所以该字段为空也表示今天未打卡；该字段不为空但不等同今天的日期，说明今日未打卡
                    habitVO.setIsDoneToday(Converter.getAsInteger(0));
                }
                habitVOList.add(habitVO);
            }
        }

        //查询条件：用户id、is_finish和愿望日期是否在未来，来选取该用户未完成的所有愿望
        QueryWrapper<Wish> wrapperWish = new QueryWrapper<>();
        wrapperWish.eq("user_id",userId);//要和数据库的一样，带下划线的不能转大写
        wrapperWish.eq("is_finish",0);
        wrapperWish.gt("wish_date",LocalDate.now());//只选取wishdate还在未来的记录
        List<Wish> wishEntities = wishService.list(wrapperWish);
        List<GetWishVO> wishVOList = new ArrayList<>();
        //获取愿望需要计算到预期达成愿望还有多少天，需要和今天的日期作比较
        for(int i=0;i<wishEntities.size();i++){
            //利用工具类计算今天到预期的相差时间,主要是要新增一个倒计时天数的字段，其实这个实体转vo应该自定义方法写在service里面
            GetWishVO wishVO = new GetWishVO();//将wish实体类转化为vo
            LocalDate wishDate = wishEntities.get(i).getWishDate();
            long ConutdownDays= LocalDate.now().until(wishDate, ChronoUnit.DAYS);
            wishVO.setConutdownDays(Converter.getAsInteger(ConutdownDays));
            System.out.println("距预期愿望完成还有多少天："+ConutdownDays);
            wishVO.setWishIcon(wishEntities.get(i).getWishIcon());
            wishVO.setWishTitle(wishEntities.get(i).getWishTitle());
            wishVO.setWishId(wishEntities.get(i).getWishId());
            wishVOList.add(wishVO);
        }
        //将两个列表添加到最终的vo之中
        GetHabitWishesVO habitWishesVO = new GetHabitWishesVO();
        habitWishesVO.setHabitVOList(habitVOList);
        habitWishesVO.setWishVOList(wishVOList);

        if(habitVOList.size() == 0 && wishVOList.size() == 0 ){
            return ApiResponse.<GetHabitWishesVO>builder().code(400).message("获取失败,该用户今天没有需要打卡的习惯和未完成的愿望").data(null).build();
        }else{
            return ApiResponse.<GetHabitWishesVO>builder().code(200).message("获取成功").data(habitWishesVO).build();
        }

    }


    //个人页 获取归档习惯
    @ApiOperation(value = "我的页/查找某用户的已归档的习惯和已完成的愿望", notes = "在归档的情况下，savedHabitList中dayNum表示坚持习惯打卡的天数，gmtModified表示习惯归档时间，gmtCreate表示习惯开始时间，可以在前端显示一段时间区间。savedWishList中的。finishTime表示愿望完成打卡的日期，类型为LocalDate；favourNum表示该愿望在许愿星中被点赞的数量。")
    @GetMapping("/getMySavedHabit/{userId}")
    @ResponseBody
    public ApiResponse<GetSavedHabitWishesVO> getMySavedHabit(@ApiParam(value="用户id",required = true) @PathVariable(value="userId",required=true) Integer userId) {
        //先判断用户是否存在
        QueryWrapper<Users> wrapperUser = new QueryWrapper<>();
        wrapperUser.eq("user_id",userId).last("limit 1");
        int isUserExist = usersService.count(wrapperUser);
        if(isUserExist == 0){
            return ApiResponse.<GetSavedHabitWishesVO>builder().code(400).message("用户id有误").data(null).build();
        }
        //依照用户id和状态（坚持中or归档）来查找出所有的合适记录，之后还要根据frequency进一步筛选
        QueryWrapper<Habit> wrapperHabit = new QueryWrapper<>();
        wrapperHabit.eq("user_id",userId);//要和数据库的一样，带下划线的不能转大写
        wrapperHabit.eq("state",2);
        List<Habit> savedHabitList = habitService.list(wrapperHabit);

        //查询条件：用户id、is_finish取该用户已完成的所有愿望
        QueryWrapper<Wish> wrapperWish = new QueryWrapper<>();
        wrapperWish.eq("user_id",userId);//要和数据库的一样，带下划线的不能转大写
        wrapperWish.eq("is_finish",1);
        List<Wish> savedWishList = wishService.list(wrapperWish);

        //将两个列表添加到最终的vo之中
        GetSavedHabitWishesVO savedHabitWishesVO = new GetSavedHabitWishesVO();
        savedHabitWishesVO.setSavedHabitList(savedHabitList);
        savedHabitWishesVO.setSavedWishList(savedWishList);

        if(savedHabitList.size() == 0 && savedWishList.size() == 0 ){
            return ApiResponse.<GetSavedHabitWishesVO>builder().code(400).message("获取失败,该用户今天没有需要打卡的习惯和未完成的愿望").data(null).build();
        }else{
            return ApiResponse.<GetSavedHabitWishesVO>builder().code(200).message("获取成功").data(savedHabitWishesVO).build();
        }

    }




}